package com.test.updater.updatefsm;

import com.test.updater.fsm.FSMException;
import com.test.updater.fsm.FSMMachine;
import com.test.updater.fsm.FSMState;
import com.test.updater.fsm.Row;
import com.test.updater.versionupdater.Control;

import java.lang.ref.WeakReference;

/**
 * Created by lmy on 2015/8/11.
 */
public class UpdateFsmMachine extends FSMMachine {
    private State.NewState mNewState;
    private State.CheckWaitState mCheckWaitState;
    private State.CheckingState mCheckingState;
    private State.CheckCancelingState mCheckCancelingState;
    private State.CheckCanceledState mCheckCanceledState;
    private State.CheckedState mCheckedState;
    private State.DownloadWaitState mDownloadWaitState;
    private State.DownloadingState mDownloadingState;
    private State.DownloadCancelingState mDownloadCancelingState;
    private State.DownloadCanceledState mDownloadCanceledState;
    private State.DownloadedState mDownloadedState;
    private State.FinishState mFinishState;

    private WeakReference<Control> mControl;                 //regiest control

    public boolean initFsm(Control control) {
        mControl = new WeakReference<Control>(control);
        return init();
    }

    @Override
    public boolean init() {
        mNewState = new State.NewState(this, mControl.get());
        mCheckWaitState = new State.CheckWaitState(this, mControl.get());
        mCheckingState = new State.CheckingState(this, mControl.get());
        mCheckCancelingState = new State.CheckCancelingState(this, mControl.get());
        mCheckCanceledState = new State.CheckCanceledState(this, mControl.get());
        mCheckedState = new State.CheckedState(this, mControl.get());
        mDownloadWaitState = new State.DownloadWaitState(this, mControl.get());
        mDownloadingState = new State.DownloadingState(this, mControl.get());
        mDownloadCancelingState = new State.DownloadCancelingState(this, mControl.get());
        mDownloadCanceledState = new State.DownloadCanceledState(this, mControl.get());
        mDownloadedState = new State.DownloadedState(this, mControl.get());
        mFinishState = new State.FinishState(this, mControl.get());

        rowTable = new Row[]{
                new Row<State.NewState, Event.CheckEvent, State.CheckWaitState>(mNewState, Event.CheckEvent.class, mCheckWaitState),
                new Row<State.CheckWaitState, Event.StartEvent, State.CheckingState>(mCheckWaitState, Event.StartEvent.class, mCheckingState),
                new Row<State.CheckWaitState, Event.CancelCheckEvent, State.CheckCancelingState>(mCheckWaitState, Event.CancelCheckEvent.class, mCheckCancelingState),
                new Row<State.CheckWaitState, Event.FinishEvent, State.CheckCancelingState>(mCheckWaitState, Event.FinishEvent.class, mCheckCancelingState),
                new Row<State.CheckWaitState, Event.DownEvent, State.CheckedState>(mCheckWaitState, Event.DownEvent.class, mCheckedState),
                new Row<State.CheckingState, Event.CancelCheckEvent, State.CheckCancelingState>(mCheckingState, Event.CancelCheckEvent.class, mCheckCancelingState),
                new Row<State.CheckCancelingState, Event.DownEvent, State.CheckCanceledState>(mCheckCancelingState, Event.DownEvent.class, mCheckCanceledState),
                new Row<State.CheckCanceledState, Event.FinishEvent, State.FinishState>(mCheckCanceledState, Event.FinishEvent.class, mFinishState),
                new Row<State.CheckCanceledState, Event.CheckEvent, State.CheckWaitState>(mCheckCanceledState, Event.CheckEvent.class, mCheckWaitState),
                new Row<State.CheckingState, Event.DownEvent, State.CheckedState>(mCheckingState, Event.DownEvent.class, mCheckedState),
                new Row<State.CheckedState, Event.FinishEvent, State.FinishState>(mCheckedState, Event.FinishEvent.class, mFinishState),
                new Row<State.CheckedState, Event.DownloadEvent, State.DownloadWaitState>(mCheckedState, Event.DownloadEvent.class, mDownloadWaitState),
                new Row<State.CheckedState, Event.CheckEvent, State.CheckWaitState>(mCheckedState, Event.CheckEvent.class, mCheckWaitState),
                new Row<State.NewState, Event.DownloadEvent, State.DownloadWaitState>(mNewState, Event.DownloadEvent.class, mDownloadWaitState),
                new Row<State.DownloadWaitState, Event.StartEvent, State.DownloadingState>(mDownloadWaitState, Event.StartEvent.class, mDownloadingState),
                new Row<State.DownloadWaitState, Event.CancelDownloadEvent, State.DownloadCancelingState>(mDownloadWaitState, Event.CancelDownloadEvent.class, mDownloadCancelingState),
                new Row<State.DownloadWaitState, Event.DownEvent, State.DownloadedState>(mDownloadWaitState, Event.DownEvent.class, mDownloadedState),
                new Row<State.DownloadWaitState, Event.FinishEvent, State.FinishState>(mDownloadWaitState, Event.FinishEvent.class, mFinishState),
                new Row<State.DownloadingState, Event.CancelDownloadEvent, State.DownloadCancelingState>(mDownloadingState, Event.CancelDownloadEvent.class, mDownloadCancelingState),
                new Row<State.DownloadCancelingState, Event.DownEvent, State.DownloadCanceledState>(mDownloadCancelingState, Event.DownEvent.class, mDownloadCanceledState),
                new Row<State.DownloadCanceledState, Event.FinishEvent, State.FinishState>(mDownloadCanceledState, Event.FinishEvent.class, mFinishState),
                new Row<State.DownloadCanceledState, Event.DownloadEvent, State.DownloadWaitState>(mDownloadCanceledState, Event.DownloadEvent.class, mDownloadWaitState),
                new Row<State.DownloadCanceledState, Event.CheckEvent, State.CheckWaitState>(mDownloadCanceledState, Event.CheckEvent.class, mCheckWaitState),
                new Row<State.DownloadingState, Event.DownEvent, State.DownloadedState>(mDownloadingState, Event.DownEvent.class, mDownloadedState),
                new Row<State.DownloadedState, Event.FinishEvent, State.FinishState>(mDownloadedState, Event.FinishEvent.class, mFinishState),
                new Row<State.DownloadedState, Event.CheckEvent, State.CheckWaitState>(mDownloadedState, Event.CheckEvent.class, mCheckWaitState),
                new Row<State.DownloadedState, Event.DownloadEvent, State.DownloadWaitState>(mDownloadedState, Event.DownloadEvent.class, mDownloadWaitState),
                new Row<State.FinishState, Event.CheckEvent, State.CheckWaitState>(mFinishState, Event.CheckEvent.class, mCheckWaitState)
        };

        return true;
    }

    @Override
    public void start() {
        mCurrentState = new WeakReference<FSMState>(mNewState);
        try {
            mNewState.enter(null);
        } catch (FSMException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void unInit() {
        mNewState = null;
        mCheckWaitState = null;
        mCheckingState = null;
        mCheckCancelingState = null;
        mCheckCanceledState = null;
        mCheckedState = null;
        mDownloadWaitState = null;
        mDownloadingState = null;
        mDownloadCancelingState = null;
        mDownloadCanceledState = null;
        mDownloadedState = null;
        mFinishState = null;
    }
}
